package com.yonyou.brigade.facade.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.yonyou.brigade.basic_init.model.BriChannel;
import com.yonyou.brigade.basic_init.model.Developer;
import com.yonyou.brigade.basic_init.service.IBriChannelService;
import com.yonyou.brigade.basic_init.service.IDeveloperService;
import com.yonyou.brigade.basic_init.service.IUserCenterService;
import com.yonyou.brigade.facade.model.ApplyInfo;
import com.yonyou.brigade.facade.service.IApplyInfoService;
import com.yonyou.brigade.facade.util.ModelConvert;
import com.yonyou.brigade.third_parties.ctrip.bigcustomer.service.ICtripBigCustomerApplyService;
import com.yonyou.brigade.third_parties.yihao.model.CLYHApplyInfo;
import com.yonyou.brigade.third_parties.yihao.model.CLYHApprovalInfo;
import com.yonyou.brigade.third_parties.yihao.service.ICLYHApplyService;
import com.yonyou.brigade.order_center.util.YHUtils;
import com.yonyou.brigade.util.operateutil.DateUtils;
import com.yonyou.brigade.util.operateutil.RedisUtils;
import com.yonyou.ybzboot.starter.common.exception.BusinessException;
import com.yonyou.ybzboot.starter.mail.model.Email;
import com.yonyou.ybzboot.starter.mail.service.IMailService;
import com.yonyou.ybzboot.starter.mongodb.dao.IMongoDao;
import com.yonyou.ybzboot.starter.mongodb.model.CriteriaMap;
import com.yonyou.ybzboot.uc.dto.UcUserDto;
import corp.openapicalls.contract.setapproval.request.SetApprovalServiceRequest;
import corp.openapicalls.contract.ticket.TicketResponse;
import corp.openapicalls.service.ticket.CorpTicketService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.sql.Timestamp;
import java.util.*;

@Service
public class ApplyInfoServiceImpl implements IApplyInfoService {

    @Autowired
    @Qualifier("briChannelServiceImpl")
    private IBriChannelService briChannelService;

    @Autowired
    private IMongoDao mongoDao;

    @Autowired
    @Qualifier("ctripBigCustomerApplyServiceImpl")
    private ICtripBigCustomerApplyService bigCustomerApplyService;

    @Autowired
    @Qualifier("userCenterServiceImpl")
    private IUserCenterService userCenterService;

    @Autowired
    @Qualifier("CLYHApplyServiceImpl")
    private ICLYHApplyService clyhApplyService;

    @Autowired
    @Qualifier("developerServiceImpl")
    private IDeveloperService developerService;

    @Autowired
    private IMailService mailService;

    @Autowired
    private YHUtils yhUtils;

    @Autowired
    private RedisUtils redisUtils;

    @Value("${brigade.cur}")
    private String curEnv;

    private Logger logger=LoggerFactory.getLogger(this.getClass());

    public void dealApplyInfo(Map applyInfoMap,String tenant) throws Exception {
        Map<String, Object> data4Mongo = new HashMap<>();
        data4Mongo.put("pushTime", DateUtils.dateToString(new Date()));
        data4Mongo.put("isSuccess", true);
        try {
            ApplyInfo applyInfo=ModelConvert.convertMapToApplyInfo(applyInfoMap,tenant);
            data4Mongo.put("data",applyInfo);
            saveApplyInfoToMonogo(data4Mongo);
            dealWithApplyInfo(applyInfoMap, tenant, applyInfo);
        } catch (Exception e) {
            updateApplyInfoToMongo(data4Mongo);
//            String applyInfo_failure = redisUtils.getValue("applyInfo_failure");
//            if (StringUtils.isEmpty(applyInfo_failure)) {
//                sendEmail(data4Mongo, e);
//                //将时间放到redis中，控制半个小时内只能发一次邮件
//                redisUtils.setKey("applyInfo_failure", String.valueOf(data4Mongo.get("pushTime")), 30);
//            }
            throw new BusinessException("处理申请单时出现异常，同步申请单未成功");
        }
    }

    private void dealWithApplyInfo(Map applyInfoMap, String tenant, ApplyInfo applyInfo) throws Exception {
        UcUserDto ucUserDto = userCenterService.getCompleteUcUserDtoByPhone(applyInfo.getPhone(),tenant);
        if(ucUserDto==null)
        {
            logger.error("获取用户为空");
            throw new BusinessException("获取用户为空,租户："+tenant+" ,手机号："+applyInfo.getPhone());
        }
        List<BriChannel> briChannelList=briChannelService.getEnableChannelByOrg(ucUserDto.getOrgPk());
        if(briChannelList!=null&&briChannelList.size()>0)
        {
            for(int i=0;i<briChannelList.size();i++)
            {
                BriChannel briChannel=briChannelList.get(i);
                if(briChannel.getIsPreApprove()==1)
                {
                    switch (briChannel.getChannel())
                    {
                        case "ctripBC":
                            JSONObject configJson=JSONObject.parseObject( briChannel.getConfig());
                            String appKey=configJson.getString("appKey");
                            String secret=configJson.getString("appSecurity");
                            TicketResponse ticketResponse = CorpTicketService.getOrderAuditTicket(appKey, secret, "1.0");
                            if (null != ticketResponse && null != ticketResponse.getStatus() && ticketResponse.getStatus().getSuccess())
                            {
                                SetApprovalServiceRequest approvalServiceRequest=ModelConvert.AppyInfoToCtripBC(applyInfo,appKey,ticketResponse.getTicket());
                                bigCustomerApplyService.pushApplyVoucherToCtrip(approvalServiceRequest);
                            }
                            else
                            {
                                logger.error("ctripBC 获取ticket报错");
                            }

                            break;

                        case "clyh":
                            if (StringUtils.isEmpty(briChannel.getConfig())) {
                                return;
                            }
                            JSONObject config = JSONObject.parseObject( briChannel.getConfig());
                            String requestid = ucUserDto.getUserId() + String.valueOf(System.currentTimeMillis());
                            String version = config.getString("version");
                            String token = yhUtils.getToken(tenant, requestid, config);
                            if (!StringUtils.isEmpty(token)){
                                CLYHApprovalInfo clyhApprovalInfo = ModelConvert.AppyInfoToCLYH(applyInfo);
                                CLYHApplyInfo clyhInfo = new CLYHApplyInfo();
                                CLYHApplyInfo.StaffInfo handoverStaffInfo = clyhInfo.new StaffInfo();
                                CLYHApplyInfo.StaffInfo submitStaffInfo = clyhInfo.new StaffInfo();

                                //申请单列表信息
                                clyhApprovalInfo.setApplyId(applyInfo.getApprovalNumber());
                                clyhApprovalInfo.setApplyPassState(Integer.parseInt(applyInfoMap.get("applyPassState").toString()));
                                clyhApprovalInfo.setApplyPurpose(applyInfoMap.get("applyPurpose").toString());
                                clyhApprovalInfo.setApplyState(Integer.parseInt(applyInfoMap.get("applyState").toString()));
                                //costCenterNo 成本中心编号   settlementEntityCode 核算主体（第三方传入） settlementEntityName 核算主体名称（第三方传入）
                                clyhApprovalInfo.setCostCenterName(applyInfoMap.get("costCenterName").toString());
                                clyhApprovalInfo.setCostCenterNo(applyInfoMap.get("costCenterNo").toString());
                                clyhApprovalInfo.setCostCenterType(Integer.parseInt(applyInfoMap.get("costCenterType").toString()));
                                clyhApprovalInfo.setSettlementEntityCode(applyInfoMap.get("settlementEntityCode").toString());
                                clyhApprovalInfo.setSettlementEntityName(applyInfoMap.get("settlementEntityName").toString());
                                clyhApprovalInfo.setUrgentType(Integer.parseInt(applyInfoMap.get("urgentType").toString()));
                                //申请事由
                                clyhApprovalInfo.setApplyReason(applyInfo.getMatters() + "&" + applyInfo.getApprovalNumber() + "&" + new Timestamp(new Date().getTime()).toString());

                                //审批人信息
                                Map handoverStaffMap = (Map) applyInfoMap.get("handoverStaff");
                                UcUserDto handoverStaff = userCenterService.getCompleteUcUserDtoByPhone(handoverStaffMap.get("phone").toString(),tenant);
                                if (handoverStaff != null){
                                    handoverStaffInfo.setStaffName(handoverStaff.getUserName());
                                    handoverStaffInfo.setEmpID(handoverStaffMap.get("empID").toString());
                                    handoverStaffInfo.setDepartment(handoverStaffMap.get("department").toString());
                                    handoverStaffInfo.setDepartmentNO(handoverStaffMap.get("departmentNO").toString());
                                } else {
                                    logger.info("审批人获取用户为空");
                                }

                                //提交人信息
                                Map submitStaffMap = (Map) applyInfoMap.get("submitStaff");
                                UcUserDto submitStaff = userCenterService.getCompleteUcUserDtoByPhone(applyInfoMap.get("phone").toString(),tenant);
                                submitStaffInfo.setStaffName(submitStaff.getUserName());
                                submitStaffInfo.setEmpID(submitStaffMap.get("empID").toString());
                                submitStaffInfo.setDepartment(submitStaffMap.get("department").toString());
                                submitStaffInfo.setDepartmentNO(submitStaffMap.get("departmentNO").toString());

                                clyhApprovalInfo.setHandoverStaff(handoverStaffInfo);
                                clyhApprovalInfo.setSubmitStaff(submitStaffInfo);

                                HashMap<String, Object> pushApplyMap = new HashMap<>();
                                List pushApplyList = new ArrayList<>();
                                pushApplyList.add(clyhApprovalInfo);
                                pushApplyMap.put("access_token",token);
                                pushApplyMap.put("data",pushApplyList);
                                pushApplyMap.put("requestid",requestid);
                                pushApplyMap.put("version",version);
                                String pushApplyStr = JSONObject.toJSONString(pushApplyMap);
                                clyhApplyService.pushApplyVoucherToCLYH(pushApplyStr);
                            }else {
                                logger.error("差旅壹号 获取token异常 :" + briChannel.getPhone());
                                throw new BusinessException("差旅壹号 获取token异常 :" + briChannel.getPhone());
                            }
                            break;
                    }
                }
            }
        } else {
            logger.error("人员所在组织未绑定第三方商旅系统");
            throw new BusinessException("人员所在组织未绑定第三方商旅系统：" + ucUserDto.getOrgPk());
        }
    }

    private void saveApplyInfoToMonogo(Map<String, Object> data4Mongo)
    {
        //存申请单详情信息
        ApplyInfo applyInfo = (ApplyInfo) data4Mongo.get("data");
        CriteriaMap criteriaMap = new CriteriaMap();
        criteriaMap.put("data.approvalNumber",applyInfo.getApprovalNumber());
        criteriaMap.put("data.fromChannel",applyInfo.getFromChannel());
        criteriaMap.put("data.tenant",applyInfo.getTenant());
        List<JSONObject> applyInfos = mongoDao.findByMap(criteriaMap,JSONObject.class,"bri_apply_info");
        if(applyInfos != null )
        {
            mongoDao.deleteByMap(criteriaMap,"bri_apply_info");
            mongoDao.getMongoTemplate().save(data4Mongo,"bri_apply_info");
        }
        else
        {
            mongoDao.getMongoTemplate().insert(data4Mongo,"bri_apply_info");
        }
    }

    private void updateApplyInfoToMongo(Map<String, Object> data4Mongo) {
        data4Mongo.put("isSuccess", false);
        if (data4Mongo.get("data") != null) {
            ApplyInfo data = (ApplyInfo) data4Mongo.get("data");
            CriteriaMap criteriaMap = new CriteriaMap();
            criteriaMap.put("data.approvalNumber", data.getApprovalNumber());
            criteriaMap.put("data.fromChannel", data.getFromChannel());
            criteriaMap.put("data.tenant",data.getTenant());
            mongoDao.update(criteriaMap, data4Mongo, "bri_apply_info");
        } else {
            mongoDao.getMongoTemplate().insert(data4Mongo, "bri_apply_info");
        }
    }

    private void sendEmail(Map<String, Object> data4Mongo, Exception e) {
        Wrapper<Developer> developerWrapper = new EntityWrapper<>();
        developerWrapper.where("type={0}", "KF");
        List<Developer> developers = developerService.selectList(developerWrapper);
        String developerEmails = "";
        for (int j = 0; j < developers.size(); j++) {
            developerEmails += developers.get(j).getEmail();
            if (j < developers.size() - 1) {
                developerEmails += ",";
            }
        }
        Email email = new Email();
        String[] emails = developerEmails.split(",");
        email.setEmail(emails);
        email.setSubject(data4Mongo.get("pushTime") + "\t" + curEnv + "环境同步申请单失败");
        email.setContent(e.getMessage());
        try {
            logger.error(e.getMessage());
            mailService.send(email);
        } catch (Exception e1) {
            logger.error("提示" + data4Mongo.get("pushTime") + "\t" + curEnv + "环境同步申请单失败的邮件发送失败！" + e1.getMessage());
        }
    }
}
